#ifndef DEFINES_H_
#define DEFINES_H_

#ifndef FINISH_ALL
#define FINISH_ALL 0
#endif

#include "../Scale/Scale.h"
#include <queue>
#include <time.h>
#include <iostream>
#include <semaphore.h>
#include <pthread.h>
using namespace std;



//TASK Structure
class Task {

public:
	// events
	string START_EVN;
	string STOP_EVN;
	string MISS_DEADLINE_EVN;
	string PREEMPT_EVN;
	string RESUM_EVN;

	//Properties
	int id;
	int executionTime;
	int period;
	int clockCounter;
	int exeCycls;
	int priority;
	string status;
	unitTime startTime;
	unitTime stopTime;
	queue<struct ExEvent> exeQueue; // task execution event like START, PREEMPTE, STOP

	// flags
	bool success;
	bool done;
	bool stopFlag;
	bool running;

	// tools
	sem_t semId;
	pthread_t taskThread;
	Scale *scale;


	Task();
	void InitTask(int pExecutionTime, int pTaskPeriod, Scale *scle, int id);
	int checkPeriod();
	void addExEvent(string event, timespec t);
	void mark(string event);
	static void *run(void *object) {

		Task *ci= ((Task *)object);
		if (!ci) return NULL;
		int ck,np;
		sched_param param;

		// tell semaphore about me
		if(sem_wait(&ci->semId)==-1)cout<<"problem to wait in rum task";

		pthread_getschedparam(ci->taskThread,NULL,&param);
		do{

		// Mark task execution start
		ci->mark(ci->START_EVN);
		ci->running=true;
		ci->exeCycls++;

		//check the next period
		np=ci->exeCycls*ci->period;
		if(ci->scale->getUniTime().unit>=ci->scale->nextPeriod ||
				(ci->scale->getUniTime().unit<np && np<ci->scale->nextPeriod))ci->scale->nextPeriod=np;

		// definition & initializations
		timespec nanoSpinTime = ci->scale->getSmallestUnit();

		// Burn CPU cycles
		for (int i = 0; i < ci->executionTime; i++) {
			ci->clockCounter++;
			nanospin(&nanoSpinTime);
			ci->checkPeriod();
		}

		//Mark task execution stop
		ci->mark(ci->STOP_EVN);
		ci->done=true;
		ci->running=false;




		// wait to next period
		ci->status="BLOCKED";
		if(sem_wait(&ci->semId)==-1)cout<<"problem to wait in rum task";

		}while(!ci->scale->finishAll);
		return NULL;
	}

};

struct ExEvent {
	string event;
	timespec time;
};

#endif
